package com.xxg.renrensearch.baidu;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baidubce.auth.DefaultBceCredentials;
import com.baidubce.services.bos.BosClient;
import com.baidubce.services.bos.BosClientConfiguration;
import com.baidubce.services.bos.model.*;
import com.xxg.renrensearch.dao.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * 百度BOS管理器
 *
 * @author xuxiaogang
 * @date 2021-12-09
 */
@Component
public class BosManager {
    private static final Logger logger = LoggerFactory.getLogger(BosManager.class);
    private final static String ACCESS_KEY = "7ed93dcf4f824d8c80a44aab4f74a8e0";
    private final static String SECRET_KEY = "04f1cea3f4e444c6a7bbfe17574705d6";
    private final static String ENDPOINT = "http://su.bcebos.com";
    private final BosClient client;
    private final static String BUCKET_NAME = "slsbu";
    private final RenrenShopGoodsDao renrenShopGoodsDao;
    private final RenrenShopGoodsOptionDao renrenShopGoodsOptionDao;
    private final ImageNotFoundDao imageNotFoundDao;

    public BosManager(RenrenShopGoodsDao renrenShopGoodsDao,
                      RenrenShopGoodsOptionDao renrenShopGoodsOptionDao, ImageNotFoundDao imageNotFoundDao) {
        this.renrenShopGoodsDao = renrenShopGoodsDao;
        this.renrenShopGoodsOptionDao = renrenShopGoodsOptionDao;
        this.imageNotFoundDao = imageNotFoundDao;
        BosClientConfiguration config = new BosClientConfiguration();
        config.setCredentials(new DefaultBceCredentials(ACCESS_KEY, SECRET_KEY));
        config.setEndpoint(ENDPOINT);
        client = new BosClient(config);
    }

    public void batchUploadImage() {
        int maxGoodsId = renrenShopGoodsDao.getMaxId();
        logger.info("处理goods:[1" + "," + maxGoodsId + "]");
        List<RenrenShopGoods> goods = renrenShopGoodsDao.selectByIdRange(1, maxGoodsId);
        for (RenrenShopGoods good : goods) {
            // 已经删除或下架到商品不处理
            if (!good.getIsDeleted() && good.getStatus()) {
                List<String> images = JSON.parseObject(good.getThumbAll(), new TypeReference<List<String>>() {
                });
                for (String image : images) {
                    uploadUrlImage(image, String.valueOf(good.getId()), String.valueOf(good.getShopId()), null);
                }
            }
        }
        logger.info("处理options");
        List<RenrenShopGoodsOption> options = renrenShopGoodsOptionDao.select();
        for (RenrenShopGoodsOption option : options) {
            uploadUrlImage(option.getThumb(), String.valueOf(option.getGoodsId()), String.valueOf(option.getShopId())
                    , String.valueOf(option.getId()));
        }
        logger.info("maxSpuId=" + maxGoodsId + ",maxSkuId=" + options.get(options.size() - 1).getId());
    }

    private boolean uploadUrlImage(String fileName, String spuId, String shopId, String skuId) {
        String imageEndPoint = "https://www.dlrszm.com/data/attachment/";
        InputStream inputStream;
        try {
            URL url = new URL(imageEndPoint + fileName);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(3 * 1000);
            inputStream = conn.getInputStream();
        } catch (FileNotFoundException e) {
            logger.error(e.getMessage());
            // 将失效图片记录进行保存，防止下次继续插入
            imageNotFoundDao.insert(new ImageNotFound(null, null, spuId, shopId, skuId, fileName));
            return false;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return false;
        }
        ObjectMetadata meta = new ObjectMetadata();
        meta.addUserMetadata("spuId", spuId);
        meta.addUserMetadata("shopId", shopId);
        if (skuId != null) {
            meta.addUserMetadata("skuId", skuId);
        }
        try {
            PutObjectResponse response = client.putObject(BUCKET_NAME, fileName, inputStream, meta);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return false;
        }
        return true;
    }

    /**
     * 如果图片不存在则上传
     *
     * @param fileName 图片名称
     * @param spuId    spuId
     * @param shopId   店铺ID
     * @param skuId    skuId
     * @return true-上传成功，false-未上传
     */
    public boolean uploadIfNotExist(String fileName, String spuId, String shopId, String skuId) {
        // 检查图片是否失效
        if (imageNotFoundDao.exists(fileName)) {
            return false;
        }
        boolean exists = client.doesObjectExist(BUCKET_NAME, fileName);
        if (!exists) {
            return uploadUrlImage(fileName, spuId, shopId, skuId);
        }
        return false;
    }

    /**
     * 列举图片信息
     *
     * @return 结果
     */
    public Set<String> listAllKeys() {
        List<String> images = new LinkedList<>();
        // 获取指定Bucket下的所有Object信息
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(BUCKET_NAME);
        listObjectsRequest.withMaxKeys(500);
        ListObjectsResponse listObjectsResponse;
        boolean isTruncated = true;
        while (isTruncated) {
            listObjectsResponse = client.listObjects(listObjectsRequest);
            isTruncated = listObjectsResponse.isTruncated();
            if (listObjectsResponse.getNextMarker() != null) {
                listObjectsRequest.withMarker(listObjectsResponse.getNextMarker());
            }
            // 遍历所有Object
            for (BosObjectSummary objectSummary : listObjectsResponse.getContents()) {
                images.add(objectSummary.getKey());
            }
        }
        return new HashSet<>(images);
    }

    /**
     * 批量删除图片，一次最多删除1000条
     *
     * @param keys 图片列表
     */
    public void deleteKeys(List<String> keys) {
        int size = 1000;
        int page = (keys.size() % size == 0) ? (keys.size() / size) : (keys.size() / size + 1);
        for (int i = 0; i < page; i++) {
            int fromIndex = i * size;
            int toIndex = fromIndex + size;
            // 最后一页
            if (i == page - 1) {
                toIndex = keys.size();
            }
            List<String> list = keys.subList(fromIndex, toIndex);
            DeleteMultipleObjectsRequest request = new DeleteMultipleObjectsRequest();
            request.setBucketName(BUCKET_NAME);
            request.setObjectKeys(list);
            DeleteMultipleObjectsResponse response = client.deleteMultipleObjects(request);
        }
    }
}
